package com.yanfan.rs232;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.yanfan.common.annotation.SysProtocol;
import com.yanfan.common.constant.YanfanConstant;
import com.yanfan.common.core.mq.DeviceReport;
import com.yanfan.common.core.mq.MQSendMessageBo;
import com.yanfan.common.core.mq.message.DeviceData;
import com.yanfan.common.core.mq.message.FunctionCallBackBo;
import com.yanfan.common.core.thingsModel.ThingsModelSimpleItem;
import com.yanfan.iot.model.ThingsModels.ValueItem;
import com.yanfan.iot.service.impl.DeviceServiceImpl;
import com.yanfan.protocol.base.protocol.IProtocol;
import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Component
@SysProtocol(name = "中诺/金驰协议&AB", protocolCode = YanfanConstant.PROTOCOL.RS232, description = "中诺/金驰协议&AB")
public class Rs232DescenDingMessageProtocol implements IProtocol {

    @Autowired
    private DeviceServiceImpl deviceService;

    @Autowired
    private RestapiMessage restapiMessage;

    @Override
    public DeviceReport decode(DeviceData data, String clientId) {
        log.error("进入RS232倒序排列协议中......");
        String StrRS232 = new String(data.getData(), StandardCharsets.UTF_8);
        log.error("=》进入RS232协议数据为【{}】",StrRS232);
        DeviceReport report = new DeviceReport();
        ByteBuf in = data.getBuf();
        //首
        int start = in.getUnsignedByte(0);
        //尾
        int messageId = in.getUnsignedByte(in.writerIndex()-1);
        //注册包解析
        String substring1 = StrRS232.substring(0, 3);
        if(substring1.equals("&AB")){
            String substring = StrRS232.substring(3,StrRS232.length()-1);
            log.debug("=>客户端id[{}]",substring);
            report.setClientId(substring);
            report.setThingsModelSimpleItem(new ArrayList<>());
            report.setMessType("RS232");
            return report;
        }

        //心跳解析
        if(start == 55 && messageId == 101){
            log.debug("=>心跳为{}:",StrRS232);
            report.setSerialNumber(clientId);
            report.setClientId(clientId);
            report.setThingsModelSimpleItem(new ArrayList<>());
            return report;
        }

        //数据解析
        if(start == 61 && (messageId == 32 || messageId == 45)){
            String substring = StrRS232.substring(1, StrRS232.length() - 1);
            log.info("报文数据为：【{}】",substring);
            //倒序解析数据
            String reversed = new StringBuilder(substring).reverse().toString();
            //包装值的返回结果
            List<ThingsModelSimpleItem> thingsModelValueItemList = new ArrayList<>();
            ThingsModelSimpleItem thingsModelSimpleItem = new ThingsModelSimpleItem();
            switch (messageId){
                case 32:
                    String str = GETStr(reversed);
                    if(!Objects.nonNull(str))
                        return null;
                    thingsModelSimpleItem.setValue(str);
                    break;
                case 45:
                    String string = GETStr(reversed);
                    if(!Objects.nonNull(string))
                        return null;
                    thingsModelSimpleItem.setValue("-"+string);
                    break;
            }
            //获取物模型
            List<ValueItem> valueItems = deviceService.selectValueItem(clientId);
            if (valueItems.size() == 1) {
                // 列表大小等于 1
                log.info("=>List contains exactly one element.");
                thingsModelSimpleItem.setId(valueItems.get(0).getId());
            } else {
                // 列表大小不等于 1（可能是 0 或多个）
                log.info("=>List does not contain exactly one element.");
                thingsModelSimpleItem.setId("weight");
            }
            thingsModelSimpleItem.setBit(false);
            thingsModelSimpleItem.setTs(new Date());
            thingsModelValueItemList.add(thingsModelSimpleItem);
            log.error("=>客户端【{}】，物模型为：{}",clientId,valueItems);
            report.setThingsModelSimpleItem(thingsModelValueItemList);
            report.setSerialNumber(clientId);
            report.setClientId(clientId);
            return report;
        }
        else {
            log.error("=>客户端【{}】，经纬度数据为：{}",clientId,StrRS232);
            //获取前面4为标识
            if(StrRS232.contains("+LBS")){
                restapiMessage.LNGAndLAT(StrRS232,clientId);
            }
            else{
                log.error("错误报文：{}",StrRS232);
            }
            report.setSerialNumber(clientId);
            report.setClientId(clientId);
            report.setThingsModelSimpleItem(new ArrayList<>());
            return report;
        }
    }

    @Override
    public FunctionCallBackBo encode(MQSendMessageBo message) {
        FunctionCallBackBo callBack = new FunctionCallBackBo();
        DeviceData data = message.getData();
        String rs232type = message.getRs232type();
        if (Objects.nonNull(data)) {
            Object body = data.getBody();
            JSONObject jsonObject = JSON.parseObject(body.toString());
            for (String key : jsonObject.keySet()) {
                String value = jsonObject.getString(key);
                String noSpaces = value.replaceAll("\\s+", "");
                callBack.setSources(noSpaces);
                if (!isAsciiHex(noSpaces))
                    return null;
                //特殊53处理
                if (noSpaces.length()!=16) {
                    //倒序解析数据
                    String reversed = new StringBuilder(noSpaces).reverse().toString();
                    String string = stringTransformAscii(reversed);
                    //拼接字段
                    String str =Objects.isNull(rs232type)? "3D53"+string:"3D52"+string;
                    byte[] byteArray = DatatypeConverter.parseHexBinary(str);
                    callBack.setMessage(byteArray);
                }
                else {
                    byte[] byteArray = DatatypeConverter.parseHexBinary(noSpaces);
                    callBack.setMessage(byteArray);
                }
            }
        }
        return callBack;
    }

    /**
     *  字符串转换为Ascii
     * @param value
     * @return
     */
    public static String stringTransformAscii(String value){
        StringBuffer sbu = new StringBuffer();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            sbu.append(Integer.toHexString((int)chars[i]));
        }
        StringBuilder string = new StringBuilder(sbu.toString());
        if (string.length()!=12) {
            for (int i = string.length(); i < 12; i++) {
                if (i % 2 == 0) {
                    string.append("3");
                } else {
                    string.append("0");
                }
            }
            return string.toString();
        }
        return string.toString();
    }

    //判断字符是否为ASCLL的十六进制数据
    public static boolean isAsciiHex(String input) {
        // 遍历字符串中的每个字符
        for (char c : input.toCharArray()) {
            // 检查字符是否是有效的十六进制字符
            if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) {
                return false; // 如果发现非十六进制字符，返回false
            }
        }
        return true; // 如果所有字符都是十六进制字符，返回true
    }

    /**
     * 数据解析为Long类型，获取真正的数据格式不为00100
     */
    public static String GETStr(String reversed){
        try {
            long num = Long.parseLong(reversed);
            log.info("=>RS232倒序解析上报的数据为：【{}】",num);
            return String.valueOf(num);
        } catch (NumberFormatException e) {
            log.error("=>数据解析：【{}】",reversed);
            List<String> results = extractSixDigitsAfterChar(reversed, new char[]{' ', '-'});
            log.info("分割数据为：【{}】",results);
            for (String result : results) {
                long l = resultsLong(result);
                if(l!=0) {
                    return String.valueOf(l);
                }
            }
            return null;
        }
    }

    /**
     * 分割字符串数据
     * @param input
     * @param delimiters
     * @return
     */
    public static List<String> extractSixDigitsAfterChar(String input, char[] delimiters) {
        List<String> results = new ArrayList<>();
        int lastDelimiterIndex = -1;
        // 遍历每个分隔符
        for (char delimiter : delimiters) {
            lastDelimiterIndex = -1;
            int index = 0;
            // 找到每个分隔符的位置
            while ((index = input.indexOf(delimiter, index)) != -1) {
                lastDelimiterIndex = index;
                index += 1; // 移动到分隔符之后的位置
            }
            // 如果找到了分隔符，提取分隔符之后的6位数字
            if (lastDelimiterIndex != -1) {
                String substring = input.substring(lastDelimiterIndex + 1);
                if (substring.length() >= 6) {
                    results.add(substring.substring(0, 6));
                }
            }
        }
        return results;
    }

    /**
     * 解析分割的字符串数据是否正常
     */
    public static long resultsLong(String results) {
        try {
            long num = Long.parseLong(results);
            log.info("=>分割数据解析上报的数据为：【{}】",num);
            return num;
        } catch (NumberFormatException e) {
            log.error("=>分割数据解析失败：【{}】",results);
            return 0L;
        }
    }

}
